Test and type-driven development
동적 타입 언어에서 테스트 주도 개발을 하는 상황과, 정적 타입 언어에서 테스트 없이 타입 검사기에만 의지하여 개발하는 상황에서의 장단점은 뭘까. 정적 타입 언어에서 테스트 주도 개발을 할 때 양자의 장점은 취하고 단점은 줄이려면 어떻게 하는 게 좋을까.
테스트 주도 개발의 장점
설계
테스트 주도 개발을 할 때 테스트 코드를 먼저 작성하면서 내가 곧 구현할 코드가 어떤 식으로 사용될지 미리 느껴볼 수 있다. 제품 디자인에서 목업을 손으로 만져보는 게 중요하고 인터랙션 디자인도 실제로 쓰면서 느껴보는 게 중요한 것과 마찬가지로 것과 마찬가지로, 소프트웨어 설계에서도 해당 설계를 사용하는 측의 코드를 느껴보는 게 중요하다.
반면, 타입 주도 개발을 할 때 타입 명세와 구현을 빠르게 오가며 점진적으로 타입을 조각하는 과정도 분명히 설계 과정이 맞지만 사용하는 측의 코드가 어떤 모양인지 느껴보는 경험을 하지는 못한다는 단점이 있다.
예제 코드
테스트 주도 개발의 결과로 얻어진 단위 테스트들은 문서 역할을 하기도 한다. 문서는 명세서, 설명서, 예제 코드 등으로 세분화할 수 있다. 단위 테스트는 세 문서의 역할을 일부 대체할 수 있고 특히 예제 코드 역할을 상대적으로 잘 대체할 수 있다.
반면, 정적 타입 언어의 명시적 타입 정의는 명세서 및 설명서 역할을 일부 대체할 수 있으나 예제 코드 역할을 하지는 못한다.
타입 주도 개발의 장점
검증
단위 테스트는 테스트 케이스에 명시된 단언들만 검증할 수 있지만 정적 타입 언어의 타입 검사기는 코드에 타입 오류가 없음을 보장해준다. “타입 오류”를 잡아준다는 게 별로 대단한 일이 아니게 느껴질 수도 있지만, 언어의 타입 시스템이 강력하면 타입 검사기의 보장 범위가 크게 늘어난다는 점을 고려할 필요가 있다. 예를 들어 Lean과 같이 의존 타입을 쓰는 언어에서는 코드의 상당 부분에 대해서 (원한다면) 동작의 무결성을 정적으로 검증할 수 있다. (모든 동작의 무결성을 정적으로 검증하는 건 원칙적으로 불가능하다.)
설계 및 명세서
내가 설계하고 있는 코드를 사용하는 느낌을 미리 느껴볼 수 없다는 점은 단점이지만, 설계를 상대적으로 엄밀하게 표현할 수 있다는 점은 장점이다. 마찬가지로, 명시적 타입 정의가 모호함 없는 명세서 역할을 하기도 한다.
타입 시스템이 강력할수록 더 많은 설계 및 명세를 담아낼 수 있게 된다.
두 TDD를 잘 조합하려면
ToDo
TODO
- 속성 기반 테스팅에 대한 고려